import app from './../app.js';
import config from './../config.js';
import Base_tools_class from './../core/base-tools.js';
import Base_layers_class from './../core/base-layers.js';
import Base_selection_class from './../core/base-selection.js';
import GUI_tools_class from './../core/gui/gui-tools.js';
import Helper_class from './../libs/helpers.js';
import { message } from 'antd'
import Image_autoAdjust_class from '../modules/image/auto_adjust.js';
import { calculateLuminance, getBackgroundColorByCanvas, getColorDiffGorgeous, parseImageData } from '../utils.js';
import Layer_raster_class from '../modules/layer/raster.js';

var instance = null;

class Slide_inpaint_class extends Base_tools_class {
  constructor(ctx, rasterCtx) {
    super();

		//singleton
		if (instance) {
			return instance;
		}
		instance = this;

		var _this = this;

		this.Base_layers = new Base_layers_class();
		this.Helper = new Helper_class();
		this.Image_autoAdjust = new Image_autoAdjust_class()
		this.Layer_raster = new Layer_raster_class();
		this.ctx = ctx;
		this.name = 'inpaint';
		this.type = null;
		this.tmpCanvas = null;
		this.tmpCanvasCtx = null;
		this.selection_coords_from = null;
		this.selection = {
			x: null,
			y: null,
			width: null,
			height: null,
		};

		var sel_config = {
			enable_background: true,
			enable_borders: true,
			enable_controls: false,
			enable_rotation: false,
			enable_move: false,
			data_function: function () {
				return _this.selection;
			},
		};
		this.mousedown_selection = null;
		this.Base_selection = new Base_selection_class(ctx, rasterCtx, sel_config, this.name);
		this.GUI_tools = new GUI_tools_class();
  }


	load() {
		var _this = this;

		//mouse events
		document.addEventListener('mousedown', function (event) {
			_this.dragStart(event);
		});
		document.addEventListener('mousemove', function (event) {
			_this.dragMove(event);
		});
		document.addEventListener('mouseup', function (event) {
			_this.dragEnd(event);
		});

		// collect touch events
		document.addEventListener('touchstart', function (event) {
			_this.dragStart(event);
		});
		document.addEventListener('touchmove', function (event) {
			_this.dragMove(event);
		});
		document.addEventListener('touchend', function (event) {
			_this.dragEnd(event);
		});

		document.addEventListener('keydown', (e) => {
      if (config.TOOL.name != _this.name) return
			var code = e.keyCode;
			if (code == 13) {
        this.fixSelection()
			}
		}, false);
	}

	onAutoAdjust(){
		this.Image_autoAdjust.auto_adjust()
	}

	dragStart(event) {
		var _this = this;
		if (config.TOOL.name != _this.name)
			return;
		_this.mousedown(event);
	}

	dragMove(event) {
		var _this = this;
		if (config.TOOL.name != _this.name)
			return;
		_this.mousemove(event);
	}

	dragEnd(event) {
		var _this = this;
		if (config.TOOL.name != _this.name)
			return;
		_this.mouseup(event);
	}
	

	mousedown(e) {
		var mouse = this.get_mouse_info(e);
		if (this.Base_selection.is_drag == false || mouse.click_valid == false) return;

		this.Helper.selectNearbyImageLayer()
		var layer = config.layer;

		// if (config.layer.type != 'image') {
		// 	message.info('这个图层必须包含一个图像，请将其转换为光栅以应用此工具')
		// 	return;
		// }

		this.mousedown_selection = JSON.parse(JSON.stringify(this.selection));
    //create new selection
    this.selection = {
      x: mouse.x,
      y: mouse.y,
      width: 0,
      height: 0,
    };
    this.type = 'create';
    this.selection_coords_from = {x: mouse.x, y: mouse.y};
	}

	mousemove(e) {
		var mouse = this.get_mouse_info(e);
		if (this.Base_selection.is_drag == false || mouse.is_drag == false)
			return;
		if (e.type == 'mousedown' && (mouse.click_valid == false) || config.layer.type != 'image') {
			return;
		}
		if (this.selection_coords_from === null) {
			return;
		}
		if (this.type == 'create') {
			//create new selection
			this.selection.width = mouse.x - mouse.click_x;
			this.selection.height = mouse.y - mouse.click_y;
			config.need_render = true;
		}
	}

	mouseup(e) {
		var mouse = this.get_mouse_info(e);
 
		if(!mouse.click_valid || this.selection.width == 0 || this.selection.height == 0) return
		
		var params = this.getParams();
		if(params.mode == 1) this.fixSmudge()
		else if(params.mode == 2) this.clearSeal()
		else if(params.mode == 3) this.deepenSeal()
	}

	// 去污点
	fixSmudge(){
		var canvas = document.createElement('canvas');
		var ctx = canvas.getContext("2d");
		if (config.layer.type !== null) {
			canvas.width = config.layer.width_original;
			canvas.height = config.layer.height_original;
			ctx.drawImage(config.layer.link, 0, 0);
		}
		else {
			canvas.width = config.WIDTH;
			canvas.height = config.HEIGHT;
		}

		var fixSelection = {
			x: (this.selection.width > 0 ? this.selection.x : (this.selection.x + this.selection.width)) - config.layer.x,
			y: (this.selection.height > 0 ? this.selection.y : (this.selection.y + this.selection.height)) - config.layer.y,
			width: Math.abs(this.selection.width),
			height: Math.abs(this.selection.height),
		}
		var rgbaArray = getBackgroundColorByCanvas(this.ctx).split(', ');
		var imageData = ctx.getImageData(fixSelection.x, fixSelection.y, fixSelection.width, fixSelection.height);
		
		for(let i=0; i<imageData.data.length; i+=4){
			imageData.data[i] = Number(rgbaArray[0])
			imageData.data[i+1] = Number(rgbaArray[1])
			imageData.data[i+2] = Number(rgbaArray[2])
			imageData.data[i+3] = Number(rgbaArray[3] * 255)
		}
		ctx.putImageData(imageData, fixSelection.x, fixSelection.y) 
				
		if (config.layer.type != null) {
			//update
			app.State.do_action(
				new app.Actions.Bundle_action('fix_tool', 'Fix Tool', [
					new app.Actions.Update_layer_image_action(canvas)
				])
			);
			this.clearSelection()
		}
	}

	// 去印章
	clearSeal(){
		let params = this.getParams();
		let canvas = document.createElement('canvas');
		let ctx = canvas.getContext("2d");
		if (config.layer.type !== null) {
			canvas.width = config.layer.width_original;
			canvas.height = config.layer.height_original;
			ctx.drawImage(config.layer.link, 0, 0);
		}
		else {
			canvas.width = config.WIDTH;
			canvas.height = config.HEIGHT;
		}
		let fixSelection = {
			x: (this.selection.width > 0 ? this.selection.x : (this.selection.x + this.selection.width)) - config.layer.x,
			y: (this.selection.height > 0 ? this.selection.y : (this.selection.y + this.selection.height)) - config.layer.y,
			width: Math.abs(this.selection.width),
			height: Math.abs(this.selection.height),
		}
		
		let backgroundColorRgba = getBackgroundColorByCanvas(this.ctx).split(', '),
				bg_r = Number(backgroundColorRgba[0]),
				bg_g = Number(backgroundColorRgba[1]),
				bg_b = Number(backgroundColorRgba[2]);

		let imageData = ctx.getImageData(fixSelection.x, fixSelection.y, fixSelection.width, fixSelection.height);
		let maxGorgeousColor = parseImageData(imageData).maxGorgeousColor;
		let gorgeousColorRgba = maxGorgeousColor.split(', '),
				r = Number(gorgeousColorRgba[0]),
				g = Number(gorgeousColorRgba[1]),
				b = Number(gorgeousColorRgba[2]),
				isMaxG =  g > r && g > b,
				isMaxB = b > r && b > g,
				maxColor = isMaxG ? g : isMaxB ? b : r,
				maxColorIndex = isMaxG ? 1 : isMaxB ? 2 : 0;
		
		for(let i=0; i<imageData.data.length; i+=4){
			let weight = Math.abs(maxColor - imageData.data[i + maxColorIndex]);	// rgb中某一类颜色权重
			
			// 如果在容差范围内
			if(weight < params.power){
				imageData.data[i] = bg_r
				imageData.data[i+1] = bg_g
				imageData.data[i+2] = bg_b
			}
		}
		ctx.putImageData(imageData, fixSelection.x, fixSelection.y) 

		if (config.layer.type != null) {
			//update
			app.State.do_action(
				new app.Actions.Bundle_action('fix_tool', 'Fix Tool', [
					new app.Actions.Update_layer_image_action(canvas)
				])
			);
			this.clearSelection()
		}
	}

	// 加深印章
	deepenSeal(){
		let params = this.getParams();
		let canvas = document.createElement('canvas');
		let ctx = canvas.getContext("2d");
		if (config.layer.type !== null) {
			canvas.width = config.layer.width_original;
			canvas.height = config.layer.height_original;
			ctx.drawImage(config.layer.link, 0, 0);
		}
		else {
			canvas.width = config.WIDTH;
			canvas.height = config.HEIGHT;
		}
		let fixSelection = {
			x: (this.selection.width > 0 ? this.selection.x : (this.selection.x + this.selection.width)) - config.layer.x,
			y: (this.selection.height > 0 ? this.selection.y : (this.selection.y + this.selection.height)) - config.layer.y,
			width: Math.abs(this.selection.width),
			height: Math.abs(this.selection.height),
		}
		

		// 先转白底
		let backgroundColorRgba_origin = getBackgroundColorByCanvas(this.ctx).split(', '),
				bg_r_origin = Number(backgroundColorRgba_origin[0]),
				bg_g_origin = Number(backgroundColorRgba_origin[1]),
				bg_b_origin = Number(backgroundColorRgba_origin[2]);

		let imageData = ctx.getImageData(fixSelection.x, fixSelection.y, fixSelection.width, fixSelection.height);

		for(let i=0; i<imageData.data.length; i+=4){
			var weight = Math.sqrt(
				0.299 * Math.pow(bg_r_origin - imageData.data[i], 2) +
				0.587 * Math.pow(bg_g_origin - imageData.data[i+1], 2) +
				0.114 * Math.pow(bg_b_origin - imageData.data[i+2], 2)
			);	// 权值

			// 如果在容差范围内
			if(weight < 8){
				imageData.data[i] = 255
				imageData.data[i+1] = 255
				imageData.data[i+2] = 255
			}
		}

		ctx.putImageData(imageData, fixSelection.x, fixSelection.y)

		// 开始处理印章
		let maxGorgeousColor = parseImageData(imageData).maxGorgeousColor;
		let gorgeousColorRgba = maxGorgeousColor.split(', '),
				r = Number(gorgeousColorRgba[0]),
				g = Number(gorgeousColorRgba[1]),
				b = Number(gorgeousColorRgba[2]),
				isMaxG =  g > r && g > b,
				isMaxB = b > r && b > g,
				maxColor = isMaxG ? g : isMaxB ? b : r,
				maxColorIndex = isMaxG ? 1 : isMaxB ? 2 : 0;

		for(let i=0; i<imageData.data.length; i+=4){
			let weight = Math.abs(maxColor - imageData.data[i + maxColorIndex]);	// rgb中某一类颜色权重
			let gorgeous = getColorDiffGorgeous(imageData.data[i], imageData.data[i+1], imageData.data[i+2]);		// 色彩艳丽度

			// 如果在容差范围内，同时艳丽度大于30
			if(weight < params.power && gorgeous > 30){
				if(maxColorIndex == 0){
					imageData.data[i] = Math.min(imageData.data[i] + 50, 255); 
					imageData.data[i+1] = g
					imageData.data[i+2] = b
				}
				else if(maxColorIndex == 1){
					imageData.data[i] = r
					imageData.data[i+1] = Math.min(imageData.data[i+1] + 50, 255);
					imageData.data[i+2] = b
				}
				else if(maxColorIndex == 2){
					imageData.data[i] = r
					imageData.data[i+1] = g
					imageData.data[i+2] = Math.min(imageData.data[i+2] + 50, 255);
				}
			}
		}
		
		// 还原原背景色
		for(let i=0; i<imageData.data.length; i+=4){
			var weight = Math.sqrt(
				0.299 * Math.pow(255 - imageData.data[i], 2) +
				0.587 * Math.pow(255 - imageData.data[i+1], 2) +
				0.114 * Math.pow(255 - imageData.data[i+2], 2)
			);	// 权值

			// 如果在容差范围内
			if(weight < 8){
				imageData.data[i] = bg_r_origin
				imageData.data[i+1] = bg_g_origin
				imageData.data[i+2] = bg_b_origin
			}
		}

		ctx.putImageData(imageData, fixSelection.x, fixSelection.y) 

		if (config.layer.type != null) {
			//update
			app.State.do_action(
				new app.Actions.Bundle_action('fix_tool', 'Fix Tool', [
					new app.Actions.Update_layer_image_action(canvas)
				])
			);
			this.clearSelection()
		}
	}

	// 转黄底
	onYellowify(){
		this.onAutoAdjust()

		var canvas = document.createElement('canvas');
		var ctx = canvas.getContext("2d");
		if (config.layer.type !== null) {
			canvas.width = config.layer.width_original;
			canvas.height = config.layer.height_original;
			ctx.drawImage(config.layer.link, 0, 0);
		}
		else {
			canvas.width = config.WIDTH;
			canvas.height = config.HEIGHT;
		}
		
		var backgroundColorRgba = getBackgroundColorByCanvas(this.ctx).split(', '),
				bg_r = Number(backgroundColorRgba[0]),
				bg_g = Number(backgroundColorRgba[1]),
				bg_b = Number(backgroundColorRgba[2]);

		var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

		for(let i=0; i<imageData.data.length; i+=4){
			var weight = Math.sqrt(
				0.299 * Math.pow(bg_r - imageData.data[i], 2) +
				0.587 * Math.pow(bg_g - imageData.data[i+1], 2) +
				0.114 * Math.pow(bg_b - imageData.data[i+2], 2)
			);	// 权值

			// 如果在容差范围内
			if(weight < 8){
				imageData.data[i] = 254
				imageData.data[i+1] = 246
				imageData.data[i+2] = 197
			}
		}
		ctx.putImageData(imageData, 0, 0)

		if (config.layer.type != null) {
			//update
			app.State.do_action(
				new app.Actions.Bundle_action('fix_tool', 'Fix Tool', [
					new app.Actions.Update_layer_image_action(canvas)
				])
			);
			this.clearSelection()
		}
	}


	// 转白底
	onWhiteify(isDoAction){
		isDoAction = isDoAction || true;
		
		this.onAutoAdjust()
		
		var canvas = document.createElement('canvas');
		var ctx = canvas.getContext("2d");
		if (config.layer.type !== null) {
			canvas.width = config.layer.width_original;
			canvas.height = config.layer.height_original;
			ctx.drawImage(config.layer.link, 0, 0);
		}
		else {
			canvas.width = config.WIDTH;
			canvas.height = config.HEIGHT;
		}
		
		var backgroundColorRgba = getBackgroundColorByCanvas(this.ctx).split(', '),
				bg_r = Number(backgroundColorRgba[0]),
				bg_g = Number(backgroundColorRgba[1]),
				bg_b = Number(backgroundColorRgba[2]);

		var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

		for(let i=0; i<imageData.data.length; i+=4){
			var weight = Math.sqrt(
				0.299 * Math.pow(bg_r - imageData.data[i], 2) +
				0.587 * Math.pow(bg_g - imageData.data[i+1], 2) +
				0.114 * Math.pow(bg_b - imageData.data[i+2], 2)
			);	// 权值

			// 如果在容差范围内
			if(weight < 5){
				imageData.data[i] = 255
				imageData.data[i+1] = 255
				imageData.data[i+2] = 255
			}
		}
		ctx.putImageData(imageData, 0, 0)

		if (isDoAction && config.layer.type != null) {
			//update
			app.State.do_action(
				new app.Actions.Bundle_action('fix_tool', 'Fix Tool', [
					new app.Actions.Update_layer_image_action(canvas)
				])
			);
			this.clearSelection()
		}
	}
	
	select_all() {
		if (config.layer.type != 'image') {
			message.info('请先选中一个包含图片的图层')
			return;
		}
		let actions = [];

		if (config.TOOL.name != this.name) {
			actions.push(
				new app.Actions.Activate_tool_action(this.name)
			);
		}
		actions.push(
			new app.Actions.Set_selection_action(0, 0, config.WIDTH, config.HEIGHT, this.selection)
		);
		app.State.do_action(
			new app.Actions.Bundle_action('select_all', 'Select All', actions)
		);
	}

	clearSelection(){
		app.State.do_action(
			new app.Actions.Bundle_action('clear_selection', 'Clear Selection', [
				new app.Actions.Reset_selection_action(this.selection)
			])
		);
	}

	render(ctx, layer) {
		//nothing
	}

	save_translate() {
		if (this.tmpCanvas == null)
			return;

		delete config.layer.link_canvas;
		app.State.do_action(
			new app.Actions.Bundle_action('selection_tool', 'Selection Tool', [
				new app.Actions.Update_layer_image_action(this.tmpCanvas)
			])
		);

		this.reset_tmp_canvas();
		config.need_render = true;
	}

	init_tmp_canvas() {
		this.tmpCanvas = document.createElement('canvas');
		this.tmpCanvasCtx = this.tmpCanvas.getContext("2d");
		this.tmpCanvas.width = config.layer.width_original;
		this.tmpCanvas.height = config.layer.height_original;
		this.tmpCanvasCtx.drawImage(config.layer.link, 0, 0);
	}

  on_activate(){
		this.setRasterMouseCursor('crosshair')
  }

  on_leave(data){
		setTimeout(()=> {
			this.setRasterMouseCursor('')
			let actions = [
				new app.Actions.Reset_selection_action(this.selection)
			];
			delete config.layer.link_canvas;
			this.reset_tmp_canvas();
			return actions;
		})
  }
	on_activate(){
    setTimeout(()=> {
      this.Layer_raster.raster();
    })
	}

  on_params_update(){
  }

	clear_selection() {
		app.State.do_action(
			new app.Actions.Bundle_action('clear_selection', 'Clear Selection', this.on_leave())
		);
	}

	reset_tmp_canvas() {
		if (this.tmpCanvas == null)
			return;
		this.tmpCanvas.width = 1;
		this.tmpCanvas.height = 1;
		this.tmpCanvas = null;
		this.tmpCanvasCtx = null;
	}
  
}
export default Slide_inpaint_class;
